﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;
using Windows.System;
using Windows.UI.Xaml;
using com.IronOne.BoardPACWinApp.Common;
using com.IronOne.BoardPACWinApp.View.UserControl;
using com.IronOne.BoardPACWinAppBO.Agenda;
using com.IronOne.BoardPACWinAppUtil.Enums;
using CompleteReader.Data;
using Microsoft.Live;
using Newtonsoft.Json;
using pdftron.SDF;

namespace com.IronOne.BoardPACWinApp.Helpers
{
    public class OneNoteHelper
    {
        #region OneNote
        private static LiveAuthClient _authClient;

        // Define the permission scopes
        private static readonly string[] Scopes = { "wl.signin", "wl.basic", "Office.OneNote_Create" };
        // Set up the Live variables


        // URI for the OneNote API
        private static readonly Uri PagesEndPoint = new Uri("https://www.onenote.com/api/v1.0/pages");
        //private string SectionName = "Quick Notes";
        private const string DefaultSectionName = "Quick Notes";

        #endregion
        

        #region OneNote

        public static async Task OneNoteProcess(AgendaItem globalSelectdAgendaItem, IDialogService dialogService, AgendaModel orgAgendaModel, NavigationParameter param)
        {
            InputMessageDialog dlg = null;
            try
            {
                dlg = new InputMessageDialog("Connecting to OneNote", Visibility.Collapsed, Visibility.Collapsed, true);
                dlg.ShowAsync();

                #region LiveAuth

                try
                {
                    _authClient = new LiveAuthClient();
                    var loginResult = await _authClient.InitializeAsync(Scopes);

                    if (loginResult.Status == LiveConnectSessionStatus.Connected)
                    {
                        var liveClient = new LiveConnectClient(loginResult.Session);
                    }
                    else
                    {
                        loginResult = await _authClient.LoginAsync(Scopes);
                        if (loginResult.Status != LiveConnectSessionStatus.Connected)
                        {
                            dlg.HideAsync();
                            await dialogService.ShowMessage("Live login unsuccessful");
                            return;
                        }
                    }
                }
                catch (LiveAuthException)
                {
                    return;
                }
                catch (Exception)
                {
                    return;
                }

                dlg.HideAsync();

                #endregion

                var docTypeName = BasePage.GetInstance().GetDocTypeName(globalSelectdAgendaItem.DocType);
                dlg = new InputMessageDialog(docTypeName + "sending to OneNote", Visibility.Collapsed,
                    Visibility.Collapsed, true);
                dlg.ShowAsync();

                #region Sending content

                var client = new HttpClient();

                // Note: API only supports JSON return type.
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                // This allows you to see what happens when an unauthenticated call is made.
                if (IsAuthenticated)
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",
                        _authClient.Session.AccessToken);

                var date = DateTime.Now.ToString("o");
                const string attachmentPartName = "pdfattachment";
                var papername = globalSelectdAgendaItem.Name;
                var title = orgAgendaModel.SelectedMeeting.MeetingName + "_" + globalSelectdAgendaItem.Name +
                            "_Annotated paper";
                var body = "<h1>Meeting name:</h1><h2>" + orgAgendaModel.SelectedMeeting.MeetingName +
                           "</h2><h1>Paper name:</h1><h2>" + globalSelectdAgendaItem.Name + "</h2><br/>";

                var attachmentRequestHtml = "<html>" +
                                            "<head>" +
                                            "<title>" + title + "</title>" +
                                            "<meta name=\"created\" content=\"" + date + "\" />" +
                                            "</head>" +
                                            "<body>" +
                                            body +
                                            "<h1>PDF file attachment:</h1>" +
                                            "<object data-attachment=\"" + papername + "\" data=\"name:" +
                                            attachmentPartName + "\" />" +
                                            "<br/><h1>Here's the content of the PDF document:</h1>" +
                                            "<img data-render-src=\"name:" + attachmentPartName + "\" alt=\"" +
                                            papername + "\" width=\"1500\" />" +
                                            "</body>" +
                                            "</html>";

                HttpResponseMessage response;

                var buff = await param.Doc.SaveToBufferAsync(SDFDocSaveOptions.e_incremental);
                using (var attachmentContent = new StreamContent(buff.AsStream()))
                {
                    attachmentContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    var createMessage = new HttpRequestMessage(HttpMethod.Post, GetPagesEndpoint("BoardPAC"))
                    {
                        Content = new MultipartFormDataContent
                        {
                            {new StringContent(attachmentRequestHtml, Encoding.UTF8, "text/html"), "Presentation"},
                            {attachmentContent, attachmentPartName}
                        }
                    };
                    // Must send the request within the using block, or the binary stream will have been disposed.
                    response = await client.SendAsync(createMessage);
                }

                var sres = await TranslateResponse(response);
                dlg.HideAsync();

                if (response.StatusCode != HttpStatusCode.Created)
                {
                    //var errorResponse = (StandardErrorResponse) sres;
                    await dialogService.ShowMessage("Unsuccessful");
                    return;
                }

                var successResponse = (CreateSuccessResponse)sres;
                var x =
                    await
                        dialogService.ShowMessageYesNoCancel(
                            docTypeName + "successfully sent. How would you like to open OneNote?",
                            DefaultButtonCommand.Yes, "Via App", "Via Browser");
                if (x == null)
                {
                    return;
                }
                if (x == true)
                {
                    await Launcher.LaunchUriAsync(new Uri(successResponse.OneNoteClientUrl));
                    return;
                }
                if (x == false)
                {
                    await Launcher.LaunchUriAsync(new Uri(successResponse.OneNoteWebUrl));
                }

                #endregion
            }
            catch (Exception)
            {
            }
            finally
            {
                if (dlg != null) dlg.HideAsync();
            }
        }

        /*private async Task<Stream> GetBinaryStream(StorageFile file)
        {
            var storageStream = await file.OpenSequentialReadAsync();
            return storageStream.AsStreamForRead();
        }*/

        public static Uri GetPagesEndpoint(string specifiedSectionName)
        {
            var sectionNameToUse = specifiedSectionName ?? DefaultSectionName;
            return new Uri(PagesEndPoint + "/?sectionName=" + sectionNameToUse);
        }

        /// <summary>
        ///     Convert the http response message into a simple structure suitable for apps to process
        /// </summary>
        /// <param name="response">The response to convert</param>
        /// <returns>A simple rsponse</returns>
        private static async Task<StandardResponse> TranslateResponse(HttpResponseMessage response)
        {
            StandardResponse standardResponse;
            if (response.StatusCode == HttpStatusCode.Created)
            {
                dynamic responseObject = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());

                standardResponse = new CreateSuccessResponse
                {
                    StatusCode = response.StatusCode,
                    OneNoteClientUrl = responseObject.links.oneNoteClientUrl.href,
                    OneNoteWebUrl = responseObject.links.oneNoteWebUrl.href
                };
            }
            else
            {
                standardResponse = new StandardErrorResponse
                {
                    StatusCode = response.StatusCode,
                    Message = await response.Content.ReadAsStringAsync()
                };
            }

            // Extract the correlation id.  Apps should log this if they want to collcet the data to diagnose failures with Microsoft support 
            IEnumerable<string> correlationValues;
            if (response.Headers.TryGetValues("X-CorrelationId", out correlationValues))
            {
                standardResponse.CorrelationId = correlationValues.FirstOrDefault();
            }

            return standardResponse;
        }

        /// <summary>
        ///     Does the object currently have a valid authenticated state
        /// </summary>
        public static bool IsAuthenticated
        {
            get { return _authClient.Session != null && !String.IsNullOrEmpty(_authClient.Session.AccessToken); }
        }

        #endregion
    }
}
